var technikaConsole = {
	i: 0,
	rows: 2,
	state: 0, // single line
	delim: '', // mutiple line delim
	history: [],

	dump: function (obj) {
		for (var i in obj) {
			technikaConsole.print(i);
		}
	},

	note: function () {
		var data = Array.prototype.join.call(arguments, ' ');

		var pane = document.getElementById('technikaConsolePane');

		var div = pane.contentDocument.createElement('div');
		div.setAttribute('class', 'note');
		div.id = 'ln' + technikaConsole.i;
		div.appendChild(pane.contentDocument.createTextNode(data.toString()));
		div.innerHTML = TH_htmlizeString(div.innerHTML);

		pane.contentDocument.body.appendChild(div);
		pane.contentDocument.location.hash = '#ln' + technikaConsole.i++;
	},

	code: function () {
		var data = Array.prototype.join.call(arguments, ' ');

		var pane = document.getElementById('technikaConsolePane');

		var div = pane.contentDocument.createElement('div');
		div.setAttribute('class', 'code');
		div.id = 'ln' + technikaConsole.i;

		var pre = pane.contentDocument.createElement('pre');
		var code = pane.contentDocument.createElement('code');

		code.appendChild(pane.contentDocument.createTextNode(data.toString()));
		pre.appendChild(code);
		div.appendChild(pre);

		pane.contentDocument.body.appendChild(div);
		pane.contentDocument.location.hash = '#ln' + technikaConsole.i++;
	},

	write: function () {
		var data = Array.prototype.join.call(arguments, ' ');

		var pane = document.getElementById('technikaConsolePane');

		var span = pane.contentDocument.createElement('span');
		span.id = 'ln' + technikaConsole.i;
		span.innerHTML = data.toString();

		pane.contentDocument.body.appendChild(span);
		pane.contentDocument.location.hash = '#ln' + technikaConsole.i++;
	},

	writeln: function () {
		var data = Array.prototype.join.call(arguments, ' ');

		var pane = document.getElementById('technikaConsolePane');

		var div = pane.contentDocument.createElement('div');
		div.id = 'ln' + technikaConsole.i;
		div.innerHTML = data.toString();

		pane.contentDocument.body.appendChild(div);
		pane.contentDocument.location.hash = '#ln' + technikaConsole.i++;
	},

	print: function () {
		var data = Array.prototype.join.call(arguments, ' ');

		var pane = document.getElementById('technikaConsolePane');

		var div = pane.contentDocument.createElement('div');
		div.id = 'ln' + technikaConsole.i;
		div.appendChild(pane.contentDocument.createTextNode(data.toString()));
		div.innerHTML = TH_htmlizeString(div.innerHTML);

		pane.contentDocument.body.appendChild(div);
		pane.contentDocument.location.hash = '#ln' + technikaConsole.i++;
	},

	error: function () {
		var data = Array.prototype.join.call(arguments, ' ');

		var pane = document.getElementById('technikaConsolePane');

		var div = pane.contentDocument.createElement('div');
		div.setAttribute('class', 'error');
		div.id = 'ln' + technikaConsole.i;
		div.appendChild(pane.contentDocument.createTextNode(data.toString()));
		div.innerHTML = TH_htmlizeString(div.innerHTML);

		pane.contentDocument.body.appendChild(div);
		pane.contentDocument.location.hash = '#ln' + technikaConsole.i++;
	},

	usage: function () {
		var data = Array.prototype.join.call(arguments, ' ');

		var pane = document.getElementById('technikaConsolePane');

		var div = pane.contentDocument.createElement('div');
		div.setAttribute('class', 'usage');
		div.id = 'ln' + technikaConsole.i;
		div.appendChild(pane.contentDocument.createTextNode(data.toString()));
		div.innerHTML = TH_htmlizeString(div.innerHTML);

		pane.contentDocument.body.appendChild(div);
		pane.contentDocument.location.hash = '#ln' + technikaConsole.i++;
	},

	clear: function () {
		var pane = document.getElementById('technikaConsolePane');
		pane.contentDocument.body.innerHTML = '';

		technikaConsole.i = 0;
	},

	reset: function () {
		technikaConsole.clear();
		technikaConsole.history = [];
	},

	report: function (name) {
		var data = Array.prototype.slice.call(arguments, 1).join(' ');

		var pane = document.getElementById('technikaConsolePane');

		var span = pane.contentDocument.createElement('span');
		span.setAttribute('class', 'report-name');
		span.appendChild(pane.contentDocument.createTextNode(name.toString()));

		var div = pane.contentDocument.createElement('div');
		div.setAttribute('class', 'report');
		div.id = 'ln' + technikaConsole.i;
		div.appendChild(span);
		div.appendChild(pane.contentDocument.createTextNode(data.toString()));
		div.innerHTML = TH_htmlizeString(div.innerHTML);

		pane.contentDocument.body.appendChild(div);
		pane.contentDocument.location.hash = '#ln' + technikaConsole.i++;
	},

	screen: function (title, name) {
		var w = TH_getSelectedBrowserWindow().open('about:blank', name);

		w.document.open();
		w.document.write(TH_readURL('chrome://technika/content/console.htm'));
		w.document.close();

		w.document.title = title;

		return w;
	},

	evalScript: function (script, path, name, args, inpt) {
		var sandbox = TH_getSandbox(window, TH_extend({
			_cmdl: this,
			_path: path,
			_name: name,
			_inpt: inpt,
			_pane: document.getElementById('technikaConsolePane'),

			dump: this.dump,
			note: this.note,
			code: this.code,

			write: this.write,
			writeln: this.writeln,

			print: this.print,
			error: this.error,

			usage: function () {
				var data = Array.prototype.join.call(arguments, ' ');

				return technikaConsole.usage.call(technikaConsole, this._name, data);
			},

			clear: this.clear,
			reset: this.reset,

			source: this.getScript,

			report: function () {
				var data = Array.prototype.join.call(arguments, ' ');

				return technikaConsole.report.call(technikaConsole, this._name, data);
			},

			screen: this.screen,

			include: function(_path) {
				var _path = TH_trimString(_path);

				if (_path[0] == '/') {
					var _pathurl = TH_parseURL(path);
					_pathurl.pathname = _path;

					_path = TH_buildURL(_pathurl);
				} else {
					var _pathurl = TH_parseURL(_path);

					if (!_pathurl.protocol) {
						_path = path.split('/').reverse().slice(1).reverse().join('/') + _path;
					}
				}

				var script = TH_readURL(_path);
				TH_evalInSandbox(script, _path, sandbox);
			}
		}, args));

		TH_evalInSandbox(TH_expandLocalBackticks(script), path, sandbox);
	},

	getScript: function (name) {
		var paths = TH_expandMacros(TH_getPref('extensions.technika.scripts.path', '.')).split(/\s*;\s*/);

		for (var i = 0; i < paths.length; i++) {
			switch (TH_getURLScheme(paths[i])) {
				case 'ftp':
				case 'file':
				case 'http':
				case 'https':
				case 'chrome':
					try {
						var url = paths[i] + '/' + name + '.js';
						var content = TH_readURL(url);

						return {path: url, content: content};
					} catch(e) {}

					break;

				default:
					try {
						var file = paths[i] + TH_getDirSeparator() + name + '.js';
						var content = TH_readFile(file);

						return {path: file, content: content};
					} catch(e) {}
			}
		}

		return null;
	},

	doCommand: function (command) {
		if (command.replace(/^\s+|\s+$/g, '') != '') {
			this.history.push(command);
			this.history.index = this.history.length;
		}

		var lines = command.split('\n');

		this.writeln('<div class="command">' + TH_escapeHTML(TH_expandMacros(TH_getPref('extensions.technika.prompt', '>> ')) + lines[0]) + '</div>');

		var script_name = '';
		var script_args = {};
		var script_inpt = '';

		if (lines.length > 1) {
			var match = lines[0].match(/([^\s]+)(?:\s+(.*))?\s*<<\s*.*?\s*$/);
			script_name = match[1];
			script_args = match[2] ? TH_expandVars(TH_parseQuery(match[2])) : {};
			script_inpt = lines.slice(1, lines.length - 1).join('\n');
		} else {
			var match = lines[0].match(/([^\s]+)(?:\s+(.*))?/);
			script_name = match[1];
			script_args = match[2] ? TH_expandVars(TH_parseQuery(match[2])) : {};
		}

		var s = this.getScript(script_name);

		if (s != null) {
			try {
				return this.evalScript(s.content, s.path, script_name, script_args, script_inpt);
			} catch (e) {
				return this.error(e);
			}
		} else {
			this.error("command '" + script_name + "' not found");
		}
	},

	setCommand: function (command) {
		this.rows = 2;
		this.state = 0;
		this.delim = '';

		var lines = command.split('\n');

		var target = document.getElementById('technikaConsolePromptMultiline');
		target.hidden = true;

		var target = document.getElementById('technikaConsolePrompt');
		target.hidden = false;

		if (lines.length > 1) {
			target.value = lines[0];
		} else {
			target.value = command;
		}

		window.setTimeout('document.getElementById("technikaConsolePrompt").focus()', 100);
	},

	handleKeys: function (event) {
		switch(event.keyCode) {
			case KeyEvent.DOM_VK_RETURN: // enter
				var command = event.target.value.toString();

				if (this.state == 0) { // is single line
					var match = command.match(/<<\s*(.*?)\s*$/);

					if (!match) {
						event.preventDefault();
						event.target.value = '';

						this.doCommand(command);
					} else {
						this.state = 1;
						this.delim = match[1];

						event.target.value = '';
						event.target.hidden = true;

						var new_target = document.getElementById('technikaConsolePromptMultiline');
						new_target.hidden = false;
						new_target.value = command + '\n';
						window.setTimeout('document.getElementById("technikaConsolePromptMultiline").focus()', 100);
					}
				} else { // is multi line
					var lines = command.split('\n');

					if (lines[lines.length - 1].replace(/\s*$/, '') == this.delim) {
						event.preventDefault();

						this.rows = 2;
						this.state = 0;
						this.delim = '';

						event.target.value = '';
						event.target.hidden = true;
						event.target.setAttribute('rows', 2);

						var new_target = document.getElementById('technikaConsolePrompt');
						new_target.hidden = false;
						window.setTimeout('document.getElementById("technikaConsolePrompt").focus()', 100);

						this.doCommand(command);
					} else {
						event.target.setAttribute('rows', this.rows++);
					}
				}

				break;
			case KeyEvent.DOM_VK_ESCAPE: // escape
				document.getElementById('cmd_technikaConsoleClose').doCommand();
				TH_getSelectedBrowserWindow().focus();

				break;

			case KeyEvent.DOM_VK_UP: // up
				event.preventDefault();

				var command = (this.history.index && this.history.index == 0) ? undefined : this.history[--this.history.index];

				if (command == undefined) {
					this.history.index = -1;
				}

				this.setCommand(command);

				break;

			case KeyEvent.DOM_VK_DOWN: // down
				event.preventDefault();

				var command = (this.history.index && this.history.index == this.history.length) ? undefined : this.history[++this.history.index];

				if (command == undefined) {
					this.history.index = this.history.length;
				}

				this.setCommand(command);

				break;
		}
	}
};
